package sk.stuba.fiit.clientApp.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.tsp.TimeStampResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import sk.stuba.fiit.clientApp.cvo.ArchiveCVO;
import sk.stuba.fiit.clientApp.cvo.ArchiveResultCVO;
import sk.stuba.fiit.clientApp.cvo.BasicPanelDataCVO;
import sk.stuba.fiit.clientApp.cvo.CertificateCVO;
import sk.stuba.fiit.clientApp.cvo.CrlCVO;
import sk.stuba.fiit.clientApp.cvo.UserDetailCVO;
import sk.stuba.fiit.clientApp.cvo.VerifyPanelDataCVO;
import sk.stuba.fiit.clientApp.service.ArchiveService;
import sk.stuba.fiit.clientApp.service.CertificateService;
import sk.stuba.fiit.clientApp.service.CrlService;
import sk.stuba.fiit.clientApp.service.CryptographyService;
import sk.stuba.fiit.clientApp.service.SignatureService;
import sk.stuba.fiit.clientApp.service.SignerService;
import sk.stuba.fiit.clientApp.service.StorageService;
import sk.stuba.fiit.clientApp.service.TimeStampService;
import sk.stuba.fiit.clientApp.util.Util;
import sk.stuba.fiit.ltasys.ws.schema.beans.ArchiveRequest;
import sk.stuba.fiit.ltasys.ws.schema.beans.SignatureRequest;


@Service("signatureService")
public class SignatureServiceImpl implements SignatureService{
	
	@Autowired
	private SignerService signerService;
	
	@Autowired
	private StorageService storageService;
	
	@Autowired
	private CertificateService certificateService;
	
	@Autowired
	private TimeStampService timeStampService;
	
	@Autowired
	private CrlService crlService;
	
	@Autowired
	private ArchiveService archiveService;

	@Autowired
	private ArchivVerifierService archivVerifierService;

	@Override
	public SignatureRequest generateSignature(BasicPanelDataCVO data) throws Exception{
		SignatureRequest result = signerService.generateSignature(data);
		 storeXMLSignature(result,data.getOutputFile(), data.getFiles());
		 return result;
	}

	public void storeXMLSignature(SignatureRequest signature, String outputFile,
			List<File> fileName) throws IOException {
		storageService.storeXMLSignature(signature, outputFile, fileName);
	}

	@Override
	public List<File> findFileBySignature(String path) throws Exception {
		return storageService.findFileBySignature(path);
	}
	
	
	
	@Override
	public boolean verifySignatureComplex(VerifyPanelDataCVO data) throws Exception {
		if(data.isArchival()){
			return archivVerifierService.verifySignatureComplex(data);
		}
		return signerService.verifySignatureComplex(data);
	}

	@Override
	public UserDetailCVO setUserAccount(String name, String password, String id) throws Exception{
		String username = name;
		 MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
		 sha1.update(password.getBytes());
		 String passw = new BigInteger(1,sha1.digest()).toString(16);
		String userId = id;
		return storageService.setUserAccount(username, passw,userId);
	}

	@Override
	public TimeStampResponse getTimeStampToken(byte[] data,
			ASN1ObjectIdentifier algorithmOid, String algorithm)
					throws Exception {
		
		return timeStampService.getTimeStampToken(data, algorithmOid, algorithm);
	}

	@Override
	public CrlCVO GetAndSaveActualCRL() throws Exception {
		
		 X509CRL crl = crlService.getActualCRL();
		 GregorianCalendar cal = new GregorianCalendar();
		 StringBuilder sb = new StringBuilder();
		 sb.append(cal.get(Calendar.DATE)).append("-").append(cal.get(Calendar.MONTH)).append("-").append(cal.get(Calendar.YEAR)).append(".crl");
		 File file = new File(sb.toString());
		 if(!file.exists()){
			 file.createNewFile();
		 }
		 storageService.saveBinaryData(file, crl.getEncoded());
		 CrlCVO result = new CrlCVO();
		 result.setCrl(crl);
		 result.setOutput(file.getAbsolutePath());
		 return result;
	}

	@Override
	public CertificateCVO getCertificateBySerialNum(String serialNum) throws Exception {
		X509Certificate cert = certificateService.getCertificateBySerialNum(serialNum);
		StringBuilder sb = new StringBuilder();
		sb.append(cert.getSerialNumber()).append(".cer");
		File file = new File(sb.toString());
		 if(!file.exists()){
			 file.createNewFile();
		 }
		 storageService.saveBinaryData(file, cert.getEncoded());
		 CertificateCVO result = new CertificateCVO();
		 result.setCertificate(cert);
		 result.setOutput(file.getAbsolutePath());
		 return result;
	}
	
	public ArchiveResultCVO archive(ArchiveCVO archiveCVO) throws Exception{
		return archiveService.archive(archiveCVO);
	}

	@Override
	public ArchiveResultCVO deleteArchivePackage(ArchiveCVO archiveCvo) throws Exception {
		return archiveService.deleteArchivePackage(archiveCvo);
	}

	@Override
	public ArchiveResultCVO obtainArchivePackage(ArchiveCVO archiveCvo) throws Exception {
		return archiveService.obtainArchivePackage(archiveCvo);
	}
	
}
